# -*- coding: utf-8 -*-
# @Time    : 2024/10/29 15:47
# @Author  : CHNJX
# @File    : jenkins_client.py
# @Desc    : jenkins 客户端封装
import threading
import gc
import jenkins
import time
from typing import Dict, List, Optional
from flask import current_app


class JenkinsClient:
    """Jenkins操作封装类"""

    def __init__(self):
        self._client = None
        self._build_lock = threading.Lock()  # 添加一个锁来同步构建操作
        self._last_client_creation = 0  # 上次创建客户端的时间戳

    @property
    def client(self) -> jenkins.Jenkins:
        current_time = time.time()
        
        # 如果客户端存在超过30分钟，重新创建以避免资源泄漏
        if self._client is None or (current_time - self._last_client_creation > 1800):
            # 如果已有客户端，先尝试关闭资源
            if self._client is not None:
                try:
                    # 释放旧客户端资源，先设为None再触发垃圾回收
                    self._client = None
                    gc.collect()
                except Exception as e:
                    current_app.logger.warning(f"关闭旧Jenkins客户端时出错: {str(e)}")
            
            max_retries = 3
            retry_count = 0
            last_error = None
            
            while retry_count < max_retries:
                try:
                    # 创建新客户端实例，添加超时设置
                    self._client = jenkins.Jenkins(
                        current_app.config['JENKINS_URL'],
                        username=current_app.config['JENKINS_USER'],
                        password=current_app.config['JENKINS_PASSWORD'],
                        timeout=30  # 添加30秒超时，避免请求无限等待
                    )
                    # 验证连接
                    self._client.get_whoami()
                    self._last_client_creation = current_time
                    current_app.logger.debug("创建了新的Jenkins客户端连接")
                    break
                except Exception as e:
                    retry_count += 1
                    last_error = e
                    current_app.logger.warning(f"Jenkins客户端连接失败 (尝试 {retry_count}/{max_retries}): {str(e)}")
                    time.sleep(2)  # 等待2秒后重试
            
            if self._client is None:
                raise jenkins.JenkinsException(f"无法创建Jenkins客户端连接: {str(last_error)}")
            
        return self._client

    def trigger_job(self, job_params: Dict, device_name: Optional[str] = None) -> Dict:
        """触发Jenkins任务"""
        try:
            with self._build_lock:  # 使用锁确保构建号的唯一性，但确保临界区尽可能小
                job_params['DEVICE_NAME'] = device_name
                
                # 确保NODE参数被传递
                if 'NODE' not in job_params:
                    job_params['NODE'] = 'KAOJI1'  # 默认节点
                
                job_name = current_app.config['JENKINS_JOB_NAME']

                # 获取队列信息，检查是否有正在等待的构建
                queue_info = self.client.get_queue_info()
                for item in queue_info:
                    if item.get('task', {}).get('name') == job_name:
                        # 等待队列中的构建完成
                        time.sleep(5)

                # 获取下一个构建号
                job_info = self.client.get_job_info(job_name)
                next_build_number = job_info['nextBuildNumber']

                # 触发构建
                queue_item = self.client.build_job(job_name, job_params)
            
            # 锁外执行不需要原子性的操作
            current_app.logger.info(f"设备 {device_name} 触发构建，节点: {job_params.get('NODE')}, 队列项ID: {queue_item}")

            # 等待构建从队列转为实际构建
            build_number = self._wait_for_queue_to_build(queue_item, job_name, timeout=60)
            if build_number:
                return {"status": "success", "build_number": build_number}
            else:
                return {"status": "error", "error": "构建未能在预期时间内开始"}

        except jenkins.JenkinsException as e:
            current_app.logger.error(f"触发任务失败: {str(e)}")
            return {"status": "error", "error": str(e)}
        except Exception as e:
            current_app.logger.error(f"触发任务时发生未知错误: {str(e)}")
            return {"status": "error", "error": f"未知错误: {str(e)}"}

    def _wait_for_queue_to_build(self, queue_item_number: int, job_name: str, timeout: int = 60) -> Optional[int]:
        """等待队列项转换为实际构建"""
        start_time = time.time()
        retry_count = 0
        max_retries = 5
        
        while time.time() - start_time < timeout:
            try:
                queue_item = self.client.get_queue_item(queue_item_number)
                retry_count = 0  # 重置重试计数
                
                if not queue_item:
                    current_app.logger.warning(f"队列项 {queue_item_number} 不存在")
                    time.sleep(2)
                    continue
                
                if 'executable' in queue_item:
                    build_number = queue_item['executable']['number']
                    current_app.logger.info(f"构建 #{build_number} 已从队列转为实际构建")

                    # 确保构建真正开始
                    if self._verify_build_started(job_name, build_number):
                        return build_number
                elif queue_item.get('cancelled'):
                    current_app.logger.error("构建被取消")
                    return None
                elif 'why' in queue_item:
                    current_app.logger.debug(f"构建在队列中等待: {queue_item['why']}")

                time.sleep(2)
            except jenkins.NotFoundException:
                current_app.logger.warning(f"队列项 {queue_item_number} 不存在")
                time.sleep(2)
            except Exception as e:
                retry_count += 1
                current_app.logger.error(f"检查队列状态时发生错误: {str(e)}")
                
                # 如果连续失败多次，考虑刷新客户端连接
                if retry_count >= max_retries:
                    current_app.logger.warning("连续多次请求失败，尝试刷新Jenkins客户端连接")
                    self._client = None  # 强制下次使用时创建新连接
                    gc.collect()  # 主动调用垃圾回收
                    retry_count = 0
                
                time.sleep(2)

        current_app.logger.error(f"等待构建超时: {timeout}秒")
        return None

    def _verify_build_started(self, job_name: str, build_number: int, timeout: int = 30) -> bool:
        """验证构建是否真正开始"""
        start_time = time.time()
        retry_count = 0
        max_retries = 3
        
        while time.time() - start_time < timeout:
            try:
                build_info = self.client.get_build_info(job_name, build_number)
                retry_count = 0  # 重置重试计数
                
                if build_info['building']:
                    return True
                time.sleep(2)
            except jenkins.NotFoundException:
                time.sleep(2)
                continue
            except Exception as e:
                retry_count += 1
                current_app.logger.error(f"验证构建状态时发生错误: {str(e)}")
                
                # 如果连续失败多次，考虑刷新客户端连接
                if retry_count >= max_retries:
                    self._client = None  # 强制下次使用时创建新连接
                    retry_count = 0
                
                return False
        return False

    def get_build_status(self, job_name: str, build_number: int) -> bool:
        """查看当前构建状态"""
        if not job_name:
            job_name = current_app.config['JENKINS_JOB_NAME']
        
        try:
            build_info = self.client.get_build_info(job_name, build_number)
            if not build_info:
                return False
            return build_info.get('building', False)
        except jenkins.NotFoundException:
            return False
        except Exception as e:
            current_app.logger.error(f"获取构建状态时发生错误: {str(e)}")
            # 连接错误时尝试刷新客户端连接
            self._client = None
            return False

    def stop_device_builds(self, device_name: str) -> bool:
        """停止指定设备的所有正在运行的构建"""
        job_name = current_app.config['JENKINS_JOB_NAME']
        success = True
        
        try:
            # 使用更小的临界区，仅在必须原子操作时使用锁
            with self._build_lock:
                # 首先检查并取消队列中的构建
                queue_info = self.client.get_queue_info()
                queue_items_to_cancel = []
                
                for item in queue_info:
                    if item.get('task', {}).get('name') == job_name:
                        try:
                            params = item.get('actions', [{}])[0].get('parameters', [])
                            device_param = next((p for p in params if p['name'] == 'DEVICE_NAME'), None)
                            if device_param and device_param['value'] == device_name:
                                queue_items_to_cancel.append(item['id'])
                        except Exception as e:
                            current_app.logger.error(f"解析队列项时发生错误: {str(e)}")
            
            # 锁外执行取消队列操作，减少锁持有时间
            for item_id in queue_items_to_cancel:
                try:
                    self.client.cancel_queue(item_id)
                    current_app.logger.info(f"已取消设备 {device_name} 的队列项 {item_id}")
                except Exception as e:
                    current_app.logger.error(f"取消队列项 {item_id} 时发生错误: {str(e)}")
                    success = False

            # 查找需要停止的构建
            builds_to_stop = []
            try:
                job_info = self.client.get_job_info(job_name)
                for build in job_info.get('builds', [])[:10]:  # 只检查最近的10个构建
                    try:
                        build_info = self.client.get_build_info(job_name, build['number'])
                        if build_info['building']:
                            params = {}
                            for action in build_info['actions']:
                                if isinstance(action, dict) and 'parameters' in action:
                                    params = {p['name']: p['value'] for p in action['parameters']}
                                    break

                            if params.get('DEVICE_NAME') == device_name:
                                builds_to_stop.append(build['number'])
                    except Exception as e:
                        current_app.logger.error(f"检查构建 #{build['number']} 时发生错误: {str(e)}")
            except Exception as e:
                current_app.logger.error(f"获取作业信息时发生错误: {str(e)}")
                success = False
            
            # 锁外停止构建，减少锁持有时间
            for build_number in builds_to_stop:
                try:
                    self.client.stop_build(job_name, build_number)
                    current_app.logger.info(f"已停止设备 {device_name} 的构建 #{build_number}")
                    # 短暂等待避免过多并发请求
                    time.sleep(0.5)
                except Exception as e:
                    current_app.logger.error(f"停止构建 #{build_number} 时发生错误: {str(e)}")
                    success = False

            return success
        except Exception as e:
            current_app.logger.error(f"停止设备构建时发生错误: {str(e)}")
            # 出现异常时尝试刷新客户端连接
            self._client = None
            return False

    def stop_all_builds(self) -> bool:
        """停止所有正在运行自动化任务的构建"""
        job_name = current_app.config['JENKINS_JOB_NAME']
        success = True
        
        try:
            # 获取job信息
            job_info = self.client.get_job_info(job_name)

            # 获取所有正在运行的构建
            running_builds = []
            for build in job_info.get('builds', []):
                build_number = build['number']
                try:
                    build_info = self.client.get_build_info(job_name, build_number)
                    if build_info.get('building'):
                        running_builds.append(build_number)
                except Exception as e:
                    current_app.logger.error(f"获取构建 #{build_number} 信息时发生错误: {str(e)}")

            if not running_builds:
                current_app.logger.warning(f"Job '{job_name}' 当前没有正在运行的构建。")
                return True

            # 停止所有运行中的构建
            for build_number in running_builds:
                try:
                    current_app.logger.info(f"正在停止构建 #{build_number}...")
                    self.client.stop_build(job_name, build_number)

                    # 避免过多并发请求导致Jenkins过载
                    time.sleep(1)
                    
                    # 检查构建是否已停止，最多等待5秒
                    max_wait = 5
                    while max_wait > 0:
                        build_info = self.client.get_build_info(job_name, build_number)
                        if not build_info.get('building'):
                            current_app.logger.info(f"构建 #{build_number} 已成功停止")
                            break
                        time.sleep(1)
                        max_wait -= 1
                    else:
                        current_app.logger.warning(f"警告: 构建 #{build_number} 可能未完全停止")

                except Exception as e:
                    current_app.logger.error(f"停止构建 #{build_number} 时发生错误: {str(e)}")
                    success = False

            # 操作结束后主动触发垃圾回收
            gc.collect()
            return success

        except jenkins.NotFoundException:
            current_app.logger.error(f"找不到Job '{job_name}'")
            return False
        except Exception as e:
            current_app.logger.error(f"操作失败: {str(e)}")
            # 出现异常时尝试刷新客户端连接
            self._client = None
            return False

    def wait_for_build_to_start(self, job_name: str, build_number: int, timeout: int = 60) -> bool:
        """
        等待构建开始运行
        Args:
            job_name: Jenkins 任务名称
            build_number: 构建号
            timeout: 超时时间（秒）
        Returns:
            bool: 构建是否成功开始
        """
        start_time = time.time()
        retry_count = 0
        max_retries = 5
        
        while time.time() - start_time < timeout:
            try:
                build_info = self.client.get_build_info(job_name, build_number)
                retry_count = 0  # 重置重试计数

                # 检查构建状态
                if build_info['building']:
                    current_app.logger.info(f"构建 #{build_number} 已开始运行")
                    return True

                # 如果构建已完成但没有运行，说明可能出现了问题
                if not build_info['building'] and build_info.get('result'):
                    current_app.logger.error(f"构建 #{build_number} 异常结束，结果: {build_info['result']}")
                    return False

                # 检查构建是否在队列中
                queue_info = self.client.get_queue_info()
                for item in queue_info:
                    if (item.get('task', {}).get('name') == job_name and
                            item.get('executable', {}).get('number') == build_number):
                        current_app.logger.debug(f"构建 #{build_number} 正在队列中等待")
                        
                # 等待一小段时间再次检查
                time.sleep(2)
                
            except jenkins.NotFoundException:
                # 构建可能尚未在Jenkins系统中创建
                current_app.logger.debug(f"构建 #{build_number} 尚未在Jenkins中创建")
                time.sleep(2)
            except Exception as e:
                retry_count += 1
                current_app.logger.error(f"等待构建启动时发生错误: {str(e)}")
                
                # 如果连续失败多次，考虑刷新客户端连接
                if retry_count >= max_retries:
                    current_app.logger.warning("连续多次请求失败，尝试刷新Jenkins客户端连接")
                    self._client = None  # 强制下次使用时创建新连接
                    retry_count = 0
                
                time.sleep(3)
                
        current_app.logger.error(f"等待构建 #{build_number} 启动超时")
        return False
        
    def get_build_info_with_retry(self, job_name: str, build_number: int, max_retries: int = 3) -> Optional[Dict]:
        """
        获取构建信息，带重试机制
        Args:
            job_name: Jenkins 任务名称
            build_number: 构建号
            max_retries: 最大重试次数
        Returns:
            Dict: 构建信息
        """
        for attempt in range(max_retries):
            try:
                return self.client.get_build_info(job_name, build_number)
            except jenkins.NotFoundException:
                return None
            except Exception as e:
                current_app.logger.error(f"获取构建信息失败 (尝试 {attempt+1}/{max_retries}): {str(e)}")
                if attempt == max_retries - 1:
                    # 最后一次尝试失败，重置客户端连接
                    self._client = None
                    return None
                time.sleep(1)
        return None

    def __del__(self):
        """析构函数，确保资源被正确释放"""
        try:
            self._client = None
            gc.collect()
        except:
            pass

    def trigger_performance_job(self, job_params: Dict) -> Dict:
        """触发性能监控Jenkins任务"""
        try:
            # 验证必要参数
            required_params = ['DEVICE_NAME', 'NODE']
            for param in required_params:
                if param not in job_params:
                    return {
                        "status": "error",
                        "error": f"缺少必要参数: {param}"
                    }
            
            device_name = job_params['DEVICE_NAME']
            node = job_params['NODE']
            
            # 确保所有参数都是字符串格式（Jenkins要求）
            jenkins_params = {
                'DEVICE_NAME': str(device_name),
                'NODE': str(node),
                'SLEEP_TIME': str(job_params.get('SLEEP_TIME', '3')),
                'DURATION_TIME': str(job_params.get('DURATION_TIME', '30')),
                'SHEET_NAME': str(job_params.get('SHEET_NAME', '')),
                'IS_CLEAR_CACHE': str(job_params.get('IS_CLEAR_CACHE', 'false')).lower()
            }
            
            current_app.logger.info(f"触发性能监控: 设备={device_name}, 节点={node}")
            
            with self._build_lock:
                # 使用性能监控的job名称
                job_name = current_app.config.get('PERFORMANCE_JOB_NAME', 'performence_minitor')

                # 获取队列信息，检查是否有正在等待的构建
                queue_info = self.client.get_queue_info()
                for item in queue_info:
                    if item.get('task', {}).get('name') == job_name:
                        # 等待队列中的构建完成
                        time.sleep(5)

                # 获取下一个构建号
                job_info = self.client.get_job_info(job_name)
                next_build_number = job_info['nextBuildNumber']

                # 触发构建
                queue_item = self.client.build_job(job_name, jenkins_params)
            
            current_app.logger.info(f"设备 {device_name} 触发性能监控构建，节点: {node}, 队列项ID: {queue_item}")

            # 等待构建从队列转为实际构建
            build_number = self._wait_for_queue_to_build(queue_item, job_name, timeout=60)
            if build_number:
                return {
                    "status": "success", 
                    "build_number": build_number
                }
            else:
                return {
                    "status": "error", 
                    "error": "性能监控构建未能在预期时间内开始"
                }

        except Exception as e:
            current_app.logger.error(f"触发性能监控任务时发生错误: {str(e)}")
            return {
                "status": "error", 
                "error": f"触发失败: {str(e)}"
            }

    def get_performance_monitor_status(self, device_name: Optional[str] = None) -> Dict:
        """获取性能监控流水线状态"""
        try:
            job_name = current_app.config.get('PERFORMANCE_JOB_NAME', 'performence_minitor')
            job_info = self.client.get_job_info(job_name)
            
            status_info = {
                'device_name': device_name,
                'running_builds': [],
                'recent_builds': [],
                'is_running': False
            }
            
            # 检查最近的构建状态
            for build in job_info.get('builds', [])[:10]:  # 检查最近10个构建
                try:
                    build_info = self.client.get_build_info(job_name, build['number'])
                    build_params = {}
                    
                    # 获取构建参数
                    for action in build_info['actions']:
                        if isinstance(action, dict) and 'parameters' in action:
                            build_params = {p['name']: p['value'] for p in action['parameters']}
                            break
                    
                    build_data = {
                        'build_number': build['number'],
                        'device_name': build_params.get('DEVICE_NAME', ''),
                        'node': build_params.get('NODE', ''),
                        'is_building': build_info['building'],
                        'result': build_info.get('result'),
                        'timestamp': build_info.get('timestamp'),
                        'duration': build_info.get('duration'),
                        'parameters': build_params
                    }
                    
                    # 如果指定了设备名称，只返回该设备的信息
                    if device_name and build_params.get('DEVICE_NAME') != device_name:
                        continue
                    
                    if build_info['building']:
                        status_info['running_builds'].append(build_data)
                        status_info['is_running'] = True
                    
                    status_info['recent_builds'].append(build_data)
                    
                except Exception as e:
                    current_app.logger.error(f"获取构建 #{build['number']} 信息时发生错误: {str(e)}")
            
            return status_info
            
        except Exception as e:
            current_app.logger.error(f"获取性能监控状态时发生错误: {str(e)}")
            return {
                'device_name': device_name,
                'running_builds': [],
                'recent_builds': [],
                'is_running': False,
                'error': str(e)
            }

    def stop_performance_monitor(self, device_name: str) -> bool:
        """停止指定设备的性能监控流水线"""
        try:
            job_name = current_app.config.get('PERFORMANCE_JOB_NAME', 'performence_minitor')
            success = True
            
            # 获取并停止正在运行的构建
            with self._build_lock:
                # 检查并取消队列中的构建
                queue_info = self.client.get_queue_info()
                queue_items_to_cancel = []
                
                for item in queue_info:
                    if item.get('task', {}).get('name') == job_name:
                        try:
                            params = item.get('actions', [{}])[0].get('parameters', [])
                            device_param = next((p for p in params if p['name'] == 'DEVICE_NAME'), None)
                            if device_param and device_param['value'] == device_name:
                                queue_items_to_cancel.append(item['id'])
                        except Exception as e:
                            current_app.logger.error(f"解析性能监控队列项时发生错误: {str(e)}")
            
            # 取消队列中的构建
            for item_id in queue_items_to_cancel:
                try:
                    self.client.cancel_queue(item_id)
                    current_app.logger.info(f"已取消设备 {device_name} 的性能监控队列项 {item_id}")
                except Exception as e:
                    current_app.logger.error(f"取消性能监控队列项 {item_id} 时发生错误: {str(e)}")
                    success = False

            # 停止正在运行的构建
            builds_to_stop = []
            try:
                job_info = self.client.get_job_info(job_name)
                for build in job_info.get('builds', [])[:10]:
                    try:
                        build_info = self.client.get_build_info(job_name, build['number'])
                        if build_info['building']:
                            params = {}
                            for action in build_info['actions']:
                                if isinstance(action, dict) and 'parameters' in action:
                                    params = {p['name']: p['value'] for p in action['parameters']}
                                    break

                            if params.get('DEVICE_NAME') == device_name:
                                builds_to_stop.append(build['number'])
                    except Exception as e:
                        current_app.logger.error(f"检查性能监控构建 #{build['number']} 时发生错误: {str(e)}")
            except Exception as e:
                current_app.logger.error(f"获取性能监控作业信息时发生错误: {str(e)}")
                success = False
            
            # 停止构建
            for build_number in builds_to_stop:
                try:
                    self.client.stop_build(job_name, build_number)
                    current_app.logger.info(f"已停止设备 {device_name} 的性能监控构建 #{build_number}")
                    time.sleep(0.5)
                except Exception as e:
                    current_app.logger.error(f"停止性能监控构建 #{build_number} 时发生错误: {str(e)}")
                    success = False

            return success
            
        except Exception as e:
            current_app.logger.error(f"停止设备性能监控时发生错误: {str(e)}")
            self._client = None
            return False

    def get_all_performance_monitors(self) -> List[Dict]:
        """获取所有性能监控流水线状态"""
        try:
            job_name = current_app.config.get('PERFORMANCE_JOB_NAME', 'performence_minitor')
            job_info = self.client.get_job_info(job_name)
            
            all_monitors = []
            device_status = {}  # 用于跟踪每个设备的状态
            
            # 检查最近的构建
            for build in job_info.get('builds', [])[:20]:  # 检查最近20个构建
                try:
                    build_info = self.client.get_build_info(job_name, build['number'])
                    build_params = {}
                    
                    # 获取构建参数
                    for action in build_info['actions']:
                        if isinstance(action, dict) and 'parameters' in action:
                            build_params = {p['name']: p['value'] for p in action['parameters']}
                            break
                    
                    device_name = build_params.get('DEVICE_NAME', '')
                    if not device_name:
                        continue
                    
                    # 如果设备还没有记录，或者当前构建更新，则更新状态
                    if device_name not in device_status or build['number'] > device_status[device_name]['build_number']:
                        device_status[device_name] = {
                            'device_name': device_name,
                            'build_number': build['number'],
                            'node': build_params.get('NODE', ''),
                            'is_running': build_info['building'],
                            'result': build_info.get('result'),
                            'timestamp': build_info.get('timestamp'),
                            'duration': build_info.get('duration'),
                            'parameters': build_params
                        }
                    
                except Exception as e:
                    current_app.logger.error(f"获取性能监控构建 #{build['number']} 信息时发生错误: {str(e)}")
            
            # 将设备状态转换为列表
            all_monitors = list(device_status.values())
            
            return all_monitors
            
        except Exception as e:
            current_app.logger.error(f"获取所有性能监控状态时发生错误: {str(e)}")
            return []

    def trigger_strategy_job(self, params):
        """触发策略自动化流水线"""
        try:
            # 使用配置中的实际Jenkins作业名称，而不是硬编码的名称
            job_name = current_app.config.get('JENKINS_JOB_NAME', 'NVR_AUTO_TEST')
            
            current_app.logger.info(f"触发策略流水线: {job_name}, 参数: {params}")
            
            with self._build_lock:
                # 获取下一个构建号
                job_info = self.client.get_job_info(job_name)
                next_build_number = job_info['nextBuildNumber']

                # 触发构建
                queue_item = self.client.build_job(job_name, parameters=params)
            
            # 等待构建开始
            build_number = self._wait_for_queue_to_build(queue_item, job_name, timeout=60)
            
            if build_number:
                current_app.logger.info(f"策略流水线触发成功, 构建号: {build_number}")
                return {'status': 'success', 'build_number': build_number}
            else:
                return {'status': 'error', 'error': '构建未能在预期时间内开始'}
                
        except Exception as e:
            current_app.logger.error(f"触发策略流水线失败: {str(e)}")
            return {'status': 'error', 'error': str(e)}

    def is_strategy_job_running(self, device_name):
        """检查特定设备的策略流水线是否正在运行"""
        try:
            # 使用配置中的实际Jenkins作业名称
            job_name = current_app.config.get('JENKINS_JOB_NAME', 'NVR_AUTO_TEST')
            
            # 获取所有正在运行的构建
            running_builds = self.client.get_running_builds()

            for build in running_builds:
                if build['name'] == job_name:
                    # 检查构建参数中是否有匹配的设备名
                    try:
                        build_info = self.client.get_build_info(job_name, build['number'])
                        # 获取构建参数
                        for action in build_info.get('actions', []):
                            if '_class' in action and action['_class'] == 'hudson.model.ParametersAction':
                                params = {p['name']: p.get('value') for p in action.get('parameters', [])}
                                if params.get('DEVICE_NAME') == device_name:
                                    current_app.logger.debug(f"发现设备 {device_name} 正在运行的构建: #{build['number']}")
                                    return True
                    except Exception as e:
                        current_app.logger.warning(f"检查构建 #{build['number']} 参数时发生错误: {str(e)}")
                        continue
            
            current_app.logger.debug(f"设备 {device_name} 没有正在运行的构建")
            return False
            
        except Exception as e:
            current_app.logger.error(f"检查策略任务状态失败: {str(e)}")
            return False  # 出错时，保守地认为它没有在运行

    def get_strategy_job_status(self, device_name):
        """获取策略作业状态"""
        try:
            job_name = current_app.config['JENKINS_JOB_NAME']  # 使用配置中的正确作业名
            
            # 获取最新的构建信息
            job_info = self.client.get_job_info(job_name)
            last_build = job_info.get('lastBuild')
            
            if not last_build:
                return {'status': 'NO_BUILDS', 'is_building': False, 'build_number': None}
            
            # 获取最新构建的详细信息
            build_number = last_build['number']
            build_info = self.client.get_build_info(job_name, build_number)
            
            # 检查构建参数是否匹配设备
            build_params = {}
            for action in build_info.get('actions', []):
                if isinstance(action, dict) and 'parameters' in action:
                    build_params = {p['name']: p['value'] for p in action['parameters']}
                    break
            
            # 如果设备名称不匹配，则查找该设备的构建
            if build_params.get('DEVICE_NAME') != device_name:
                # 检查最近的几个构建
                for build in job_info.get('builds', [])[:5]:  # 检查最近5个构建
                    try:
                        build_info = self.client.get_build_info(job_name, build['number'])
                        build_params = {}
                        for action in build_info.get('actions', []):
                            if isinstance(action, dict) and 'parameters' in action:
                                build_params = {p['name']: p['value'] for p in action['parameters']}
                                break
                        
                        if build_params.get('DEVICE_NAME') == device_name:
                            build_number = build['number']
                            break
                    except Exception:
                        continue
                else:
                    # 没有找到该设备的构建
                    return {'status': 'NO_DEVICE_BUILDS', 'is_building': False, 'build_number': None}
            
            return {
                'status': build_info.get('result', 'RUNNING'),
                'is_building': build_info.get('building', False),
                'build_number': build_number
            }
            
        except Exception as e:
            current_app.logger.error(f"获取策略作业状态失败: {str(e)}")
            return {'status': 'ERROR', 'is_building': False, 'build_number': None}

    def stop_strategy_job(self, device_name: str) -> bool:
        """停止指定设备的策略作业"""
        try:
            current_app.logger.info(f"准备停止设备 {device_name} 的策略作业...")
            
            # 复用现有的stop_device_builds方法
            result = self.stop_device_builds(device_name)
            
            if result:
                current_app.logger.info(f"成功停止设备 {device_name} 的策略作业")
            else:
                current_app.logger.warning(f"停止设备 {device_name} 的策略作业时出现问题")
            
            return result
            
        except Exception as e:
            current_app.logger.error(f"停止设备 {device_name} 的策略作业失败: {str(e)}")
            return False
